#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>


//1 其实数组名是数组首元素的地址
//但是有2个例外：
//1.sizeof(数组名)，这里的数组名表示整个数组，计算的是整个数组的大小，单位是字节//sizeof(*数组名),这里的数组名也还是数组首元素地址
//2.&数组名，这里的数组名也表示整个数组，取出的是整个数组的地址
//除此之外，所有的数组名都是数组首元素的地址
//&arr[0]、arr、&arr它们写的都是首元素(首字节)地址，但类型不同了


//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	           //以这种形式打印
//	printf("&arr = %p\n", &arr[0]);
//	printf("arr  = %p\n", arr);
//
//	printf("\n\n");
//
//	printf("%d\n", sizeof(arr));
//
//	printf("\n\n");
//	
//	printf("&arr[0]     = %p\n", &arr[0]);//int*性质类型
//	printf("&arr[0] + 1 = %p\n", &arr[0] + 1);//元素的地址
//
//	printf("arr         = %p\n", arr);
//	printf("arr + 1     = %p\n", arr + 1);//元素的地址
//
//	printf("&arr        = %p\n", &arr);
//	printf("&arr + 1    = %p\n", &arr + 1);//数组的地址
//	return 0;
//}
//
//
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int i = 0;
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	/*int* p = &arr[0];*/int* p = arr;
//	for (i = 0;i < sz;i++)
//	{
//		//scanf("%d", &arr[i]);
//		scanf("%d", p + i);//p+i是下标为i元素的地址
//		//scanf("%d",arr + i);
//	}
//	for (i = 0;i < sz;i++)
//	{                                   //编译器其实是这样子读的
//		//printf("%d ", arr[i]);//arr[i] <==> *(arr + i) = *(i + arr) = i[arr] 都等价
//		printf("%d ", *(p + i));   //[]仅仅是个操作符而已，意义还是看整体
//		//printf("%d ",*(arr + i));	   ^
//	}                                //|
//	return 0;                        //|
//}    //形参这边是创建了变量  //两种写法都可以意义一样的
//void text(char brr[1])//-->(char* brr)   //其实这个[1]里面的数字压根就没去用
//{      //形参这边创建数组其实是创建相应的指针变量
//	printf("%d\n", sizeof(brr));
//	printf("brr  =%p\n", brr);
//	printf("brr+1=%p\n", brr + 1);
//	printf("hehe\n");
//	int a = 0;
//	printf("a    =%p\n", a);
//	printf("a+1  =%p\n", a + 1);
//}
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	printf("%d\n", sizeof(arr));
//	printf("%d\n", sizeof(*arr));//这里的arr还是数组首元素地址
//	int sz1 = sizeof(arr) / sizeof(*arr);
//	printf("sz1  = %d\n",sz1);
//	printf("arr  =%p\n", arr);
//	printf("arr+1=%p\n", arr + 1);
//	text(arr);//arr是数组名，数组名表示数组首元素的地址
//	//数组传参的本质，传递的是数组首元素的地址
//	char crr[10];
//	printf("crr  =%d\n", sizeof(crr));
//	return 0;
//}


//2 冒泡排序


//int count = 0;//计算比较次数
//void my_scanf(int* p, int az)
//{
//	int i = 0;
//	for (i = 0;i < az;i++)
//	{
//		scanf("%d", p + i);
//	}
//}    //等价int p[]
//void paixu(int* p, int bz)
//{
//	int i = 0;//一次做完把这次范围内的最大放右边
//	//int* d = p;//总之还得再创建一个变量，最后使初始p得以存在
//	//确定趟数
//	for (i = 0;i < bz - 1;i++)
//	{
//		//继续用*p的正确correct --> p = d;
//		int* q = p;//想用*p correc but still mistake --> int* p = arr;想赋地址arr但arr名称传不过来的
//		int j = 0;//放在它们所能碰范围的最右边，每一次比完所要碰的范围-1，因为后面的范围去访问比都没意义
//		int a = 1;
//		//每一趟内部的比较
//		for (j = 0;j < bz - 1 - i;j++)//j < sz - 1  //写成每一次全都去访问比也没问题
//		{
//			count++;//至少9顿，9+8或9+8+7……顿  //与下面比较同级，比较多少次count++就执行多少次就得多少次
//			//十个数字访问9次且从角标0开始,进来时的p是0~8,p+1的存在p访问到的总范围是0~9
//			//下一次时访问8次，进来的p是0~7,访问到的是0~8，最后一个数便不在访问范围了不可能动
//			//I make mistake --> 用*p两循环外创建的变量不去更新
//			if (*q > *(q + 1))//if (arr[j] > arr[j+1])
//			{
//				a = 0;
//				//交换
//				//promote --> //变地址产生多个地址搜得到里面的值//角标形式直接取，就不用去变地址就不用再创变量了
//				int change = 0;
//				change = *q;//promote --> change = arr[j];
//				*q = *(q + 1);//promote --> arr[j] = arr[i+1];
//				*(q + 1) = change;//promote --> arr[i+1] = change;
//			}//p第一次时为0，结束后为1，第九次时为8，结束后为9
//			q++;//九次为0~8做
//		}//p初始值0，共进行9次加9次1，p最后出去时到9，看每次里加后的位置是1到9，看每次里加前的位置是0到8，每次里的不同位置值不一样
//		if (a == 1)//如果发现这一趟只交换了一顿说明这趟结束后已完成了，或者看再下一顿的0交换说明已完成，这里用的是后者
//		{
//			break;
//		}
//	}
//}
//void print(int* p, int sz)
//{
//	int i = 0;
//	for (i = 0;i < sz;i++)
//	{
//		printf("%d ", *(p + i));//p相当于0的
//	}
//}
////void my_scanf(int* p, int sz);
//int main()
//{
//	int arr[10] = { 0 };
//	int sz = sizeof(arr) / sizeof(*arr);
//	my_scanf(arr, sz);//只要my_scanf是定义声明过的，就会前后头找、跨文件找
//	//排序 - 写一个函数完成数组的排序，排成升序
//	paixu(arr, sz);//使用冒泡排序
//	print(arr, sz);
//	printf("\ncount = %d\n", count);
//	return 0;
//}
////如果函数要写后头，得在前头声明
////void my_scanf(int* p, int sz)
////{
////	int i = 0;
////	for (i = 0;i < sz;i++)
////	{
////		scanf("%d", p + i);
////	}
////}


//3 二级指针


//int main()
//{
//	int a = 10;
//	int* pa = &a;
//	int** paa = &pa;
//	printf("%d\n", **paa);
//	**paa = 200;
//	printf("%d\n", a);
//	return 0;
//}


//4 指针数组


////(1)
//int main()
//{
//	int a = 10;
//	int b = 20;
//	int c = 30;
//	//int* pa = &a;
//	//int* pb = &b;
//	//int* pc = &c;
//	int* arr[3] = { &a,&b,&c };
//	int i = 0;
//	for (i = 0;i < 3;i++)
//	{
//		printf("%d ", *arr[i]);
//	}
//	return 0;
//}


//5 指针数组模拟二维数组
//arr[i] <==> *(arr + i)
//地址[步数] <==> 地址相对位置加步数解
//(不包一头直接前走)
//地址与步数位置可调


//int main()
//{
//	int arr1[5] = { 1,2,3,4,5 };
//	int arr2[5] = { 2,3,4,5,6 };
//	int arr3[5] = { 3,4,5,6,7 };
//	int* arr[3] = { arr1,arr2,arr3};
//	//这里的指针arr能代到这15个整型元素
//	int i = 5;
//	int j = 0;//指针相当于代，代多少看其最深摸瓜程度
//	for (i = 0;i < 3;i++)
//	{//来此总循环的初始化步骤，一次总循环一次
//		for (j = 0;j < 5;j++)
//		{//用指针数组(一维数组)模拟出了二维数组的效果
//			printf("%d ", arr[i][j]);
//		}
//		printf("\n");
//	}
//	return 0;
//}


//6


// int main()
// {
// 	int arr[] = { 1,2,3,4,5 };
// 	printf("%p\n", &arr);//地址都是以首元素首字节地址为载体
// 	printf("%p\n", arr);
// 	return 0;
// }